package org.apache.jena.arq.querybuilder;
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.Arrays;
import java.util.List;

import org.apache.jena.arq.querybuilder.clauses.WhereClause;
import org.apache.jena.graph.Node;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.*;

/**
 * Create expressions.
 *
 * NodeValue contains a number of static functions to make a number of node
 * functions.
 *
 * @see org.apache.jena.sparql.expr.NodeValue
 *
 * Function names here map as closely as possible to the tag names for the
 * generated expression.
 *
 */
public class ExprFactory {

    private final PrefixMapping pMap;

    /**
     * Constructs an expression factor with the specified prefix definitions.
     *
     * @param pMap the PrefixMapping to use in the expressions.
     */
    public ExprFactory(PrefixMapping pMap) {
        this.pMap = pMap;
    }

    /**
     * Constructs an expression factory with the prefix definitions found in
     * {@code PrefixMapping.Extended}
     *
     * @see PrefixMapping#Extended
     */
    public ExprFactory() {
        this(PrefixMapping.Extended);
    }

    // expr 0 functions

    /**
     * implements rand() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-rand
     *
     * @see org.apache.jena.sparql.expr.E_Random
     * @return E_Random instance
     */
    public final E_Random rand() {
        return new E_Random();
    }

    /**
     * implements struuid() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-struuid
     *
     * @see org.apache.jena.sparql.expr.E_StrUUID
     * @return E_StrUUID instance
     */
    public final E_StrUUID struuid() {
        return new E_StrUUID();
    }

    /**
     * implements uuid() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-uuid
     *
     * @see org.apache.jena.sparql.expr.E_UUID
     * @return E_UUID instance
     */
    public final E_UUID uuid() {
        return new E_UUID();
    }

    /**
     * Returns the current ARQ name and version number as a string.
     *
     * @see org.apache.jena.sparql.expr.E_Version
     * @return E_Version instance
     */
    public final E_Version version() {
        return new E_Version();
    }

    /**
     * implements now() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-now
     *
     * @see org.apache.jena.sparql.expr.E_Now
     * @return E_Now instance
     */
    public final E_Now now() {
        return new E_Now();
    }

    // expr 1 functions

    /**
     * implements bound() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bound
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Bound
     *
     * @param expr the expression to check.
     * @return E_Bound instance
     */
    public final E_Bound bound(Object expr) {
        return new E_Bound(asExpr(expr));
    }

    /**
     * implements datatype() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-datatype
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Datatype
     *
     * @param expr the expression to check.
     * @return E_Datatype instance
     */
    public final E_Datatype datatype(Object expr) {
        return new E_Datatype(asExpr(expr));
    }

    /**
     * implements day() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-day
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     *
     * @param expr the expression to check.
     * @return E_Datatype instance
     */
    public final E_DateTimeDay day(Object expr) {
        return new E_DateTimeDay(asExpr(expr));
    }

    /**
     * implements hours() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-hours
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeHours
     *
     * @param expr the expression to check.
     * @return E_DateTimeHours instance
     */
    public final E_DateTimeHours hours(Object expr) {
        return new E_DateTimeHours(asExpr(expr));
    }

    /**
     * implements minutes() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-minutes
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeMinutes
     *
     * @param expr the expression to check.
     * @return E_DateTimeMinutes instance
     */
    public final E_DateTimeMinutes minutes(Object expr) {
        return new E_DateTimeMinutes(asExpr(expr));
    }

    /**
     * implements month() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-month
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeMonth
     *
     * @param expr the expression to check.
     * @return E_DateTimeMonth instance
     */
    public final E_DateTimeMonth month(Object expr) {
        return new E_DateTimeMonth(asExpr(expr));
    }

    /**
     * implements seconds() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-seconds
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeSeconds
     *
     * @param expr the expression to check.
     * @return E_DateTimeSeconds instance
     */
    public final E_DateTimeSeconds seconds(Object expr) {
        return new E_DateTimeSeconds(asExpr(expr));
    }

    /**
     * implements timezone() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-timezone
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeTimezone
     *
     * @param expr the expression to check.
     * @return E_DateTypeTimezone instance
     */
    public final E_DateTimeTimezone timezone(Object expr) {
        return new E_DateTimeTimezone(asExpr(expr));
    }

    /**
     * implements tz() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-tz
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeTZ
     *
     * @param expr the expression to check.
     * @return E_DateTimeTZ instance
     */
    public final E_DateTimeTZ tz(Object expr) {
        return new E_DateTimeTZ(asExpr(expr));
    }

    /**
     * implements year() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-year
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_DateTimeYear
     *
     * @param expr the expression to check.
     * @return E_DateTimeYear instance
     */
    public final E_DateTimeYear year(Object expr) {
        return new E_DateTimeYear(asExpr(expr));
    }

    /**
     * implements iri() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-iri
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_IRI
     *
     * @param expr the expression to check.
     * @return E_IRI instance
     */
    public final E_IRI iri(Object expr) {
        return new E_IRI(asExpr(expr));
    }

    /**
     * implements isBlank() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-isBlank
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_IsBlank
     *
     * @param expr the expression to check.
     * @return E_isBlank instance
     */
    public final E_IsBlank isBlank(Object expr) {
        return new E_IsBlank(asExpr(expr));
    }

    /**
     * implements isIRI() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-isIRI
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_IsIRI
     *
     * @param expr the expression to check.
     * @return E_IsIRI instance
     */
    public final E_IsIRI isIRI(Object expr) {
        return new E_IsIRI(asExpr(expr));
    }

    /**
     * implements isLiteral() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-isLiteral
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_IsLiteral
     *
     * @param expr the expression to check.
     * @return E_IsLiteral instance
     */
    public final E_IsLiteral isLiteral(Object expr) {
        return new E_IsLiteral(asExpr(expr));
    }

    /**
     * implements isNumeric() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-isNumeric
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_IsNumeric
     *
     * @param expr the expression to check.
     * @return E_IsNumeric instance
     */
    public final E_IsNumeric isNumeric(Object expr) {
        return new E_IsNumeric(asExpr(expr));
    }

    /**
     * implements lang() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-lang
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Lang
     *
     * @param expr the expression to check.
     * @return E_Lang instance
     */
    public final E_Lang lang(Object expr) {
        return new E_Lang(asExpr(expr));
    }

    /**
     * implements not() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-not
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LogicalNot
     *
     * @param expr the expression to check.
     * @return E_LogicalNot instance
     */
    public final E_LogicalNot not(Object expr) {
        return new E_LogicalNot(asExpr(expr));
    }

    /**
     * implements abs() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-abs
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NumAbs
     *
     * @param expr the expression to check.
     * @return E_NumAbs instance
     */
    public final E_NumAbs abs(Object expr) {
        return new E_NumAbs(asExpr(expr));
    }

    /**
     * implements ceil() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-ceil
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NumCeiling
     *
     * @param expr the expression to check.
     * @return E_NumCeiling instance
     */
    public final E_NumCeiling ceil(Object expr) {
        return new E_NumCeiling(asExpr(expr));
    }

    /**
     * implements floor() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-floor
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NumFloor
     *
     * @param expr the expression to check.
     * @return E_NumFloor instance
     */
    public final E_NumFloor floor(Object expr) {
        return new E_NumFloor(asExpr(expr));
    }

    /**
     * implements round() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-round
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NumRound
     *
     * @param expr the expression to check.
     * @return E_Round instance
     */
    public final E_NumRound round(Object expr) {
        return new E_NumRound(asExpr(expr));
    }

    /**
     * implements str() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-str
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Str
     *
     * @param expr the expression to check.
     * @return E_Str instance
     */
    public final E_Str str(Object expr) {
        return new E_Str(asExpr(expr));
    }

    /**
     * implements encode() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-encode
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrEncodeForURI
     *
     * @param expr the expression to check.
     * @return E_StrEncodedForURI instance
     */
    public final E_StrEncodeForURI encode(Object expr) {
        return new E_StrEncodeForURI(asExpr(expr));
    }

    /**
     * implements strlen() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strlen
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrLength
     *
     * @param expr the expression to check.
     * @return E_StrLength instance
     */
    public final E_StrLength strlen(Object expr) {
        return new E_StrLength(asExpr(expr));
    }

    /**
     * implements lcase() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-lcase
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrLowerCase
     *
     * @param expr the expression to check.
     * @return E_StrLowerCase instance
     */
    public final E_StrLowerCase lcase(Object expr) {
        return new E_StrLowerCase(asExpr(expr));
    }

    /**
     * implements ucase() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-ucase
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrUpperCase
     *
     * @param expr the expression to check.
     * @return E_StrUpperCase instance
     */
    public final E_StrUpperCase ucase(Object expr) {
        return new E_StrUpperCase(asExpr(expr));
    }

    /**
     * implements unary minus as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_UnaryMinus
     *
     * @param expr the expression to check.
     * @return E_UnaryMinus instance
     */
    public final E_UnaryMinus minus(Object expr) {
        return new E_UnaryMinus(asExpr(expr));
    }

    /**
     * implements unary plus as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_UnaryPlus
     *
     * @param expr the expression to check.
     * @return E_UnaryPlus instance
     */
    public final E_UnaryPlus plus(Object expr) {
        return new E_UnaryPlus(asExpr(expr));
    }

    /**
     * implements md5() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-md5
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_MD5
     *
     * @param expr the expression to check.
     * @return E_MD5 instance
     */
    public final E_MD5 md5(Object expr) {
        return new E_MD5(asExpr(expr));
    }

    /**
     * implements sha1() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sha1
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SHA1
     *
     * @param expr the expression to check.
     * @return E_SHA1 instance
     */
    public final E_SHA1 sha1(Object expr) {
        return new E_SHA1(asExpr(expr));
    }

    /**
     * implements sha224() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sha224
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SHA224
     *
     * @param expr the expression to check.
     * @return E_SHA224 instance
     */
    public final E_SHA224 sha224(Object expr) {
        return new E_SHA224(asExpr(expr));
    }

    /**
     * implements sha256() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sha256
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SHA256
     *
     * @param expr the expression to check.
     * @return E_SHA256 instance
     */
    public final E_SHA256 sha256(Object expr) {
        return new E_SHA256(asExpr(expr));
    }

    /**
     * implements sha384() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sha384
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SHA384
     *
     * @param expr the expression to check.
     * @return E_SHA384 instance
     */
    public final E_SHA384 sha384(Object expr) {
        return new E_SHA384(asExpr(expr));
    }

    /**
     * implements sha512() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sha512
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SHA512
     *
     * @param expr the expression to check.
     * @return E_SHA512 instance
     */
    public final E_SHA512 sha512(Object expr) {
        return new E_SHA512(asExpr(expr));
    }

    // expr2 functions

    /**
     * implements addition as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Add
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_Add instance
     */
    public final E_Add add(Object expr1, Object expr2) {
        return new E_Add(asExpr(expr1), asExpr(expr2));
    }

    // E_Cast has a private constructor and seems not to be used.
    // public final E_Cast cast( Expr expr1, Expr expr2 )
    // {
    // return new E_Cast( expr1, expr2 );
    // }
    /**
     * implements division as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Divide
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_Devide instance
     */
    public final E_Divide divide(Object expr1, Object expr2) {
        return new E_Divide(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements equality as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Equals
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_Equals instance
     */
    public final E_Equals eq(Object expr1, Object expr2) {
        return new E_Equals(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements greater than as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_GreaterThan
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_GreaterThan instance
     */
    public final E_GreaterThan gt(Object expr1, Object expr2) {
        return new E_GreaterThan(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements greater than or equal as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_GreaterThanOrEqual
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_GreaterThanOrEqual instance
     */
    public final E_GreaterThanOrEqual ge(Object expr1, Object expr2) {
        return new E_GreaterThanOrEqual(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements langMatches() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-langMatches
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LangMatches
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_LangMatches instance
     */
    public final E_LangMatches langMatches(Object expr1, Object expr2) {
        return new E_LangMatches(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements less than as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LessThan
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_LessThan instance
     */
    public final E_LessThan lt(Object expr1, Object expr2) {
        return new E_LessThan(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements less than or equal as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LessThanOrEqual
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_LessThanOrEqual instance
     */
    public final E_LessThanOrEqual le(Object expr1, Object expr2) {
        return new E_LessThanOrEqual(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements logical and as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LogicalAnd
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_LogicalAnd instance
     */
    public final E_LogicalAnd and(Object expr1, Object expr2) {
        return new E_LogicalAnd(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements logical or as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_LogicalOr
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_LogicalOr instance
     */
    public final E_LogicalOr or(Object expr1, Object expr2) {
        return new E_LogicalOr(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements multiplication s per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Multiply
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_Multiply instance
     */
    public final E_Multiply multiply(Object expr1, Object expr2) {
        return new E_Multiply(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements not equals as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NotEquals
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_NotEquals instance
     */
    public final E_NotEquals ne(Object expr1, Object expr2) {
        return new E_NotEquals(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements sameTerm() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-sameTerm
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_SameTerm
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_SameTerm instance
     */
    public final E_SameTerm sameTerm(Object expr1, Object expr2) {
        return new E_SameTerm(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strafter() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strafter
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrAfter
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrAfter instance
     */
    public final E_StrAfter strafter(Object expr1, Object expr2) {
        return new E_StrAfter(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strbefore() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strbefore
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrBefore
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrBefore instance
     */
    public final E_StrBefore strbefore(Object expr1, Object expr2) {
        return new E_StrBefore(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements contains() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-contains
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrContains
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrContains instance
     */
    public final E_StrContains contains(Object expr1, Object expr2) {
        return new E_StrContains(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strdt() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strdt
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrDatatype
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrDatatype instance
     */
    public final E_StrDatatype strdt(Object expr1, Object expr2) {
        return new E_StrDatatype(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strends() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strends
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrEndsWith
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrEndsWith instance
     */
    public final E_StrEndsWith strends(Object expr1, Object expr2) {
        return new E_StrEndsWith(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strlang() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strlang
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrLang
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrLang instance
     */
    public final E_StrLang strlang(Object expr1, Object expr2) {
        return new E_StrLang(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements strstarts() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-strstarts
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrStartsWith
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_StrStartsWith instance
     */
    public final E_StrStartsWith strstarts(Object expr1, Object expr2) {
        return new E_StrStartsWith(asExpr(expr1), asExpr(expr2));
    }

    /**
     * implements subtraction as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Subtract
     *
     * @param expr1 the first expression.
     * @param expr2 the second expression.
     * @return E_Subtract instance
     */

    public final E_Subtract subtract(Object expr1, Object expr2) {
        return new E_Subtract(asExpr(expr1), asExpr(expr2));
    }

    // expr3 functions

    /**
     * implements if() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-if
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_If
     *
     * @param condition the condition to check.
     * @param thenExpr the expression to execute if condition is true.
     * @param elseExpr the expression to execute if condition is false.
     * @return an E_Conditional instance.
     */
    public final E_If cond(Expr condition, Expr thenExpr, Expr elseExpr) {
        return new E_If(condition, thenExpr, elseExpr);
    }

    // exprN functions
    /**
     * implements bnode() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bnode
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_BNode
     *
     * @param expr1 the blank node id.
     * @return an Expr instance
     */
    public final Expr bnode(Object expr1) {
        return E_BNode.create(asExpr(expr1));
    }

    /**
     * implements bnode() as per SPARQL 1.1 spec
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bnode
     *
     * @see org.apache.jena.sparql.expr.E_BNode
     *
     * @return an Expr instance.
     */
    public final Expr bnode() {
        return E_BNode.create();
    }

    /**
     * Creates a function call as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rFunctionCall
     *
     * @see org.apache.jena.sparql.expr.E_Call
     *
     * The first argument is the function to call
     *
     * @param args the arguments to the function.
     * @return an E_Call instance.
     */
    public final E_Call call(ExprList args) {
        return new E_Call(args);
    }

    /**
     * implements coalesce() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-coalesce
     *
     * @see org.apache.jena.sparql.expr.E_Coalesce
     *
     * @param args the arguments to the function.
     * @return an E_Coalesce instance.
     */
    public final E_Coalesce coalesce(ExprList args) {
        return new E_Coalesce(args);
    }

    /**
     * implements coalesce() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-coalesce
     *
     * @see org.apache.jena.sparql.expr.E_Coalesce
     *
     * @param args the arguments to the function.
     * @return an E_Coalesce instance.
     */
    public final E_Coalesce coalesce(Object... args) {
        return new E_Coalesce(asList(args));
    }

    /**
     * Creates a function call as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rFunctionCall
     *
     * @see org.apache.jena.sparql.expr.E_Function
     *
     * @param name the name of the function.
     * @param args the arguments to the function.
     * @return an E_Function instance.
     */
    public final E_Function function(String name, ExprList args) {
        return new E_Function(name, args);
    }

    /**
     * implements "not in" as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-not-in
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NotOneOf
     *
     * @param expr the expression that is not in the list
     * @param list the list of expressions.
     * @return an E_NotOneOf instance.
     */
    public final E_NotOneOf notin(Object expr, ExprList list) {
        return new E_NotOneOf(asExpr(expr), list);
    }

    /**
     * implements "not in" as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-not-in
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_NotOneOf
     *
     * @param expr the expression that is not in the list
     * @param list the list of expressions.
     * @return an E_NotOneOf instance.
     */
    public final E_NotOneOf notin(Object expr, Object... list) {
        return new E_NotOneOf(asExpr(expr), asList(list));
    }

    /**
     * implements "in" as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-in
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_OneOf
     *
     * @param expr the expression that is not in the list
     * @param list the list of expressions.
     * @return an E_OneOf instance.
     */
    public final E_OneOf in(Object expr, ExprList list) {
        return new E_OneOf(asExpr(expr), list);
    }

    /**
     * implements "in" as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-in
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_OneOf
     *
     * @param expr the expression that is not in the list
     * @param list the list of expressions.
     * @return an E_OneOf instance.
     */
    public final E_OneOf in(Object expr, Object... list) {
        return new E_OneOf(asExpr(expr), asList(list));
    }

    /**
     * implements regex() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex
     *
     * Converts objects to an Expr objects via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Regex
     *
     * @param expr string to match.
     * @param pattern the pattern to match
     * @param flags the regex flags
     * @return an E_Regex instance.
     */
    public final E_Regex regex(Object expr, Object pattern, Object flags) {
        return new E_Regex(asExpr(expr), asExpr(pattern), asExpr(flags));
    }

    /**
     * implements regex() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex
     *
     * Converts expr to an Expr object via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_Regex
     *
     * @param expr string to match.
     * @param pattern the pattern to match
     * @param flags the regex flags
     * @return an E_Regex instance.
     */
    public final E_Regex regex(Object expr, String pattern, String flags) {
        return new E_Regex(asExpr(expr), pattern, flags);
    }

    /**
     * implements concat() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-concat
     *
     * @see org.apache.jena.sparql.expr.E_StrConcat
     *
     * @param list the list of arguments to concatenate
     * @return an E_StrConcat instance
     */
    public final E_StrConcat concat(ExprList list) {
        return new E_StrConcat(list);
    }

    /**
     * implements concat() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-concat
     *
     * @see org.apache.jena.sparql.expr.E_StrConcat
     *
     * @param list the list of arguments to concatenate
     * @return an E_StrConcat instance
     */
    public final E_StrConcat concat(Object... list) {
        return new E_StrConcat(asList(list));
    }

    /**
     * implements replace() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-replace
     *
     * Converts Objects to an Expr objects via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrReplace
     *
     * @param arg the string literal to replace
     * @param pattern the pattern to replace in the string literal.
     * @param replacement the string literal to replace the pattern with.
     * @param flags the flags that control replacement options.
     * @return an E_StrReplace instance
     */
    public final E_StrReplace replace(Object arg, Object pattern, Object replacement, Object flags) {
        return new E_StrReplace(asExpr(arg), asExpr(pattern), asExpr(replacement), asExpr(flags));
    }

    /**
     * implements replace() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-replace
     *
     * Converts Objects to an Expr objects via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrReplace
     *
     * @param arg the string literal to replace
     * @param pattern the pattern to replace in the string literal.
     * @param replacement the string literal to replace the pattern with.
     * @return an E_StrReplace instance
     */
    public final E_StrReplace replace(Object arg, Object pattern, Object replacement) {
        return new E_StrReplace(asExpr(arg), asExpr(pattern), asExpr(replacement), null);
    }

    /**
     * implements substr() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-substr
     *
     * Converts Objects to an Expr objects via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrSubstring
     *
     * @param src the expression to extract the substring from.
     * @param loc the location within the expression string to start
     * @param len the length of the string to extract.
     *
     * @return an E_Substring instance.
     */
    public final E_StrSubstring substr(Object src, Object loc, Object len) {
        return new E_StrSubstring(asExpr(src), asExpr(loc), asExpr(len));
    }

    /**
     * implements substr() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-substr
     *
     * Converts Objects to an Expr objects via expr()
     *
     * @see #asExpr(Object)
     * @see org.apache.jena.sparql.expr.E_StrSubstring
     *
     * @param src the expression to extract the substring from.
     * @param loc the location within the expression string to start
     *
     * @return an E_Substring instance.
     */
    public final E_StrSubstring substr(Object src, Object loc) {
        return new E_StrSubstring(asExpr(src), asExpr(loc), null);
    }
    // expr op

    /**
     * implements exists() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-filter-exists
     *
     * @see org.apache.jena.sparql.expr.E_Exists
     *
     * @param whereClause A WhereClause to check existence of.
     * @return an E_Exists instance,
     */
    public final E_Exists exists(WhereClause<?> whereClause) {
        return new E_Exists(whereClause.getWhereHandler().getClause());
    }

    /**
     * implements not exists() as per the SPARQL 11 query definition.
     *
     * https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-filter-exists
     *
     * @see org.apache.jena.sparql.expr.E_NotExists
     *
     * @param whereClause the argument to the function.
     * @return an E_NotExists instance.
     */
    public final E_NotExists notexists(WhereClause<?> whereClause) {
        return new E_NotExists(whereClause.getWhereHandler().getClause());
    }

    // exprnone
    /**
     * Should probably be called "null" but that is a reserved work. An expression
     * that can be used in place of null.
     *
     * @see org.apache.jena.sparql.expr.ExprNone
     *
     * @return an ExprNone instance
     */
    public final ExprNone none() {
        return (ExprNone) Expr.NONE;
    }

    /**
     * Converts the object to a ExprVar.
     * <ul>
     * <li>If the object is an ExprVar return it</li>
     * <li>Will return null if the object is "*" or Node_RuleVariable.WILD</li>
     * <li>otherwise create an ExprVar from {AbstractQuerybuilder.makeVar}
     * </ul>
     *
     * @see Converters#makeVar(Object)
     *
     * @param o the object to convert.
     * @return an ExprVar
     */
    public final ExprVar asVar(Object o) {
        if (o instanceof ExprVar) {
            return (ExprVar) o;
        }
        Var v = Converters.makeVar(o);
        return v == null ? null : new ExprVar(v);
    }

    /**
     * Not really an Expr but a container of exprs.
     *
     * @param args the list of expressons.
     * @return the expression list.
     */
    public final ExprList asList(Object... args) {
        // make sure the list is modifyable
        List<Expr> lst = Arrays.asList(args).stream().map(arg -> asExpr(arg)).toList();
        return new ExprList(lst);
    }

    /**
     * Not really an Expr but a container of exprs. creates an empty list.
     *
     * @return the empty expression list.
     */
    public final ExprList list() {
        return new ExprList();
    }

    /**
     * Convert the object into an expression using the query's PrefixMapping
     *
     * @param o the object to convert.
     * @return the Expr.
     */
    public final Expr asExpr(Object o) {
        return asExpr(o, pMap);
    }

    /**
     * Convenience method to call AbstractQueryBuilder.quote
     *
     * @see Converters#quoted(String)
     * @param s the string to quote
     * @return the quotes string.
     * @deprecated use {@link Converters#quoted(String)}
     */
    @Deprecated
    public final String quote(String s) {
        return Converters.quoted(s);
    }

    /**
     * Create an expression from an object.
     *
     * <b>this method does not parse strings to expressions.</b> to parse strings to
     * expressions see {AbstractQueryBuilder.makeExpr}
     *
     * <ul>
     * <li>If the object is null returns none()</li>
     * <li>If the object is an expression return it</li>
     * <li>If the object fronts a node and is not a var make a NodeVar</li>
     * <li>otherwise calls var()</li>
     * </ul>
     *
     * @see #asVar(Object)
     * @see Converters#makeVar(Object)
     *
     * @param o the object to create the expression from
     * @return Expr
     */
    public static final Expr asExpr(Object o, PrefixMapping pMap) {
        if (o == null) {
            return Expr.NONE;
        }
        if (o instanceof Expr) {
            return (Expr) o;
        }
        Node n = Converters.makeNode(o, pMap);

        if (n.isVariable()) {
            return new ExprVar(Var.alloc(n));
        }
        return NodeValue.makeNode(n);

    }

}
